GDK/Win32: Force GLES if running on ARM64
authorChun-wei Fan <fanchunwei@src.gnome.org>
Tue, 7 May 2019 07:09:03 +0000 (00:09 -0700)
committerChun-wei Fan <fanchunwei@src.gnome.org>
Thu, 30 Jul 2020 06:30:13 +0000 (14:30 +0800)
If GLES support is enabled on Windows, force GLES mode if we are running
on a ARM64 version of Windows (i.e. Windows 10 for ARM).

This is required as ARM64 versions of Windows only provide a software
implementation of OpenGL 1.1/1.2, which is not enough for our purposes.
Thus, we could make instead use the GLES support provided via Google's
libANGLE (which emulates OpenGL/ES 3 with Direct3D 9/11), so that we
can run GtkGLArea programs under OpenGL/ES in ARM64 versions of Windows.

Note that eventually we could update the libepoxy build files for Windows
to not check nor enable WGL when building for ARM64 Windows, as the WGL
items do not work, although they do build.

gdk/win32/gdkdisplay-win32.c
gdk/win32/gdkdisplay-win32.h
gdk/win32/gdkglcontext-win32.c

index 4c060437dabdb645302904088f00e720d563f9c6..a1c0b26e0b7c3b4202e09ff0df0a19aded628ded 100644 (file)
 # include <epoxy/egl.h>
 #endif
 
+#ifndef IMAGE_FILE_MACHINE_ARM64
+# define IMAGE_FILE_MACHINE_ARM64 0xAA64
+#endif
+
 static int debug_indent = 0;
 
 /**
@@ -880,6 +884,40 @@ _gdk_win32_enable_hidpi (GdkWin32Display *display)
     }
 }
 
+static void
+_gdk_win32_check_on_arm64 (GdkWin32Display *display)
+{
+  static gsize checked = 0;
+
+  if (g_once_init_enter (&checked))
+    {
+      HMODULE kernel32 = LoadLibraryW (L"kernel32.dll");
+
+      if (kernel32 != NULL)
+        {
+          display->cpu_funcs.isWow64Process2 =
+            (funcIsWow64Process2) GetProcAddress (kernel32, "IsWow64Process2");
+
+          if (display->cpu_funcs.isWow64Process2 != NULL)
+            {
+              USHORT proc_cpu = 0;
+              USHORT native_cpu = 0;
+
+              display->cpu_funcs.isWow64Process2 (GetCurrentProcess (),
+                                                  &proc_cpu,
+                                                  &native_cpu);
+
+              if (native_cpu == IMAGE_FILE_MACHINE_ARM64)
+                display->running_on_arm64 = TRUE;
+            }
+
+          FreeLibrary (kernel32);
+        }
+
+      g_once_init_leave (&checked, 1);
+    }
+}
+
 static void
 gdk_win32_display_init (GdkWin32Display *display)
 {
@@ -888,6 +926,7 @@ gdk_win32_display_init (GdkWin32Display *display)
   display->monitors = G_LIST_MODEL (g_list_store_new (GDK_TYPE_MONITOR));
 
   _gdk_win32_enable_hidpi (display);
+  _gdk_win32_check_on_arm64 (display);
 
   /* if we have DPI awareness, set up fixed scale if set */
   if (display->dpi_aware_type != PROCESS_DPI_UNAWARE &&
index 0264ee82cd964361f85bf31cd9c6d4797d334e70..b9bfaeb2e11ceaf6d0f0d21e6c5e81a29428128b 100644 (file)
@@ -69,6 +69,13 @@ typedef struct _GdkWin32User32DPIFuncs
   funcIsProcessDPIAware isDpiAwareFunc;
 } GdkWin32User32DPIFuncs;
 
+/* Detect running architecture */
+typedef BOOL (WINAPI *funcIsWow64Process2) (HANDLE, USHORT *, USHORT *);
+typedef struct _GdkWin32KernelCPUFuncs
+{
+  funcIsWow64Process2 isWow64Process2;
+} GdkWin32KernelCPUFuncs;
+
 struct _GdkWin32Display
 {
   GdkDisplay display;
@@ -131,6 +138,10 @@ struct _GdkWin32Display
 
   /* Message filters */
   GList *filters;
+
+  /* Running CPU items */
+  guint running_on_arm64 : 1;
+  GdkWin32KernelCPUFuncs cpu_funcs;
 };
 
 struct _GdkWin32DisplayClass
index d52c16e2cbd8cd0b18de535408de9b550bc2c8ad..056b6513556e981191eb20c5b1d099f48bc6c118 100644 (file)
@@ -540,7 +540,8 @@ _gdk_win32_display_init_gl (GdkDisplay *display)
 #ifdef GDK_WIN32_ENABLE_EGL
   EGLDisplay egl_disp;
 
-  disable_wgl = GDK_DISPLAY_DEBUG_CHECK (display, GL_GLES);
+  disable_wgl = GDK_DISPLAY_DEBUG_CHECK (display, GL_GLES) ||
+                display_win32->running_on_arm64;
 #endif
 
   if (display_win32->have_wgl